<?php

namespace Icsoc\IvrBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Class IvrTransformationCommand
 * @package Icsoc\IvrBundle\Command
 */
class IvrTransformationCommand extends ContainerAwareCommand
{
    /** @var array 不需要转化的企业 */
    private $notTranVccCode = array(
        '1014091503',
    );
    /** 图片路径 */
    const IMG_URL = '/bundles/icsocivr/images/';
    /**
     * 图片对应
     * @var array
     */
    private $icon = array(
        '1' => 'gongzuoshijian.png',
        '2' => 'bofangyuyin.png',
        '3' => 'anjiandaohang.png',
        '5' => 'zhuanjinengzu.png',
        '6' => 'liuyan.png',
        '7' => 'guaji.png',
        '30' => 'anjian.png',
        '50' => 'zhuanjieshibai.png',
    );

    /**
     * Configures the current command.
     */
    protected function configure()
    {
        $this
            ->setName('ivr:transformation')
            ->setDescription('ivr转化')
            ->addOption('vcc_code', null, InputOption::VALUE_OPTIONAL, '企业代码')
            ->addOption('ivr_id', null, InputOption::VALUE_OPTIONAL, 'ivr的id');
    }

    /**
     * Executes the current command.
     *
     * This method is not abstract because you can use this class
     * as a concrete class. In this case, instead of defining the
     * execute() method, you set the code to execute by passing
     * a Closure to the setCode() method.
     *
     * @param InputInterface $input An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     *
     * @return null|int null or 0 if everything went fine, or an error code
     *
     * @throws \LogicException When this abstract method is not implemented
     *
     * @see setCode()
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln("start");
        $vccCode = $input->getOption('vcc_code');
        $ivrId = $input->getOption('ivr_id');
        /*
        if (empty($vccCode) && empty($ivrId)) {
            $output->writeln("vcc_code and ivr_id is not empty"); //保险不能都为空；
            exit;
        }*/
        $where = '';
        if (!empty($vccCode)) {
            $vccCodes = explode(',', $vccCode);
            $vccCodes = array_diff($vccCodes, $this->notTranVccCode); //过滤掉不需要转化的；
            $vccCode = "'".implode("','", $vccCodes)."'";
            //$output->writeln($vccCodes);
            //exit;
            $where .= !empty($vccCode) ? " AND vcc_code IN ({$vccCode}) " : '';
        }
        //$where.= !empty($ivrId) ? " AND ivr_id IN ({$ivrId}) " : '';
        $notVccCode = "'".implode("','", $this->notTranVccCode)."'";
        $where .= !empty($this->notTranVccCode) ? " AND vcc_code NOT IN ({$notVccCode}) " : '';
        $conn = $this->getContainer()->get('doctrine.dbal.default_connection');
        //$assets = $this->;
        //获取老版本的ivr，ivr_conent,ivr_info
        $list = $conn->fetchAll("SELECT ivr_content,ivr_id,vcc_id,ivr_info FROM win_ivr WHERE ivr_ver = 0 ".$where);
        $reg = '/(\[.*\])/';
        foreach ($list as $row) {
            $res = json_decode($row['ivr_content'], true);
            if (empty($res)) {
                continue;
            }
            $newRes = $queIds = $nodes = $pids = $allPid = $navArr = $newJsonArr = $childArr = array();
            //处理ivr_content;
            foreach ($res as $val) {
                $node = 'node'.$val['id'];
                $newJsonArr['name'] = preg_replace($reg, '', $val['name']);
                $newJsonArr['type'] = $val['type'];
                $newJsonArr['isParent'] = $val['isParent'];
                $newJsonArr['isRealNode'] = true;
                $newJsonArr['nodeStatus'] = true;
                $newJsonArr['tId'] = $val['tId'];
                $newJsonArr['parentTId'] = 'tree_'.(isset($val['pId']) ? $val['pId'] : 0);
                $newJsonArr['zAsync'] = false;
                $newJsonArr['isFirstNode'] = $val['isFirstNode'];
                $newJsonArr['isLastNode'] = $val['isLastNode'];
                $newJsonArr['isAjaxing'] = $val['isAjaxing'];
                $newJsonArr['checked'] = $val['checked'];
                $newJsonArr['checkedOld'] = $val['checkedOld'];
                $newJsonArr['nocheck'] = false;
                $newJsonArr['chkDisabled'] = false;
                $newJsonArr['halfCheck'] = false;
                $newJsonArr['check_Child_State'] = 0;
                $newJsonArr['check_Focus'] = $val['check_Focus'];
                $newJsonArr['isHover'] = isset($val['isHover']) ? $val['isHover'] : '';
                $newJsonArr['editNameFlag'] = false;
                $newJsonArr['nodeClass'] = array('color' => 'green');
                $allPid[$val['id']] = $val['pId']; //存放所有父节点；配合下面的pids 来删除不存在子类的节点；
                $nodes[$node] = array(
                    'name' => preg_replace($reg, '', $val['name']),
                    'id' => $node,
                    'type' => $val['type'],
                );
                if (isset($this->icon[$val['type']])) {
                    $newJsonArr['icon'] = self::IMG_URL.$this->icon[$val['type']];
                } else {
                    $newJsonArr['icon'] = self::IMG_URL.'anjian.png';
                    $newJsonArr['type'] = $nodes[$node]['type'] = 30; //具体按键；
                    $pids[] = $val['id']; //存放当前按键的id 以便后续判断是否有子节点
                }
                if (isset($val['pId']) && !empty($val['pId']) && $val['pId'] != 'null') {
                    $nodes[$node]['parentId'] = 'node'.$val['pId'];
                }
                if (isset($val['pId']) && $val['pId'] && $val['pId'] != 'null') {
                    $nodes['node'.$val['pId']]['jump'] = $node;
                }
                if (isset($val['open'])) {
                    $newJsonArr['open'] = $val['open'];
                }
                switch ((int) $newJsonArr['type']) {
                    case 2: //播放语音节点;
                        $newJsonArr['sound'] = $nodes[$node]['sound'] = $this->proSound($val['playfile']);
                        $newJsonArr['bkeystop'] = $nodes[$node]['bkeystop'] = $val['bkeystop'];
                        $newJsonArr['play_times'] = $nodes[$node]['play_times'] = '1';
                        break;
                    case 5: //转技能组；需要插入转技能组失败节点；
                        $id = rand().$val['id'];
                        $queArr = $newJsonArr;
                        $queArr['id'] = $id;
                        $queArr['name'] = '转接失败';
                        $queArr['condition'] = 'queue_fail';
                        $queArr['type'] = '50';
                        $queArr['icon'] = self::IMG_URL.$this->icon['50'];
                        $queArr['level'] = $val['level'] + 1;
                        $queArr['tId'] = 'tree_'.$id;
                        $queArr['parentTId'] = 'tree_'.(isset($val['pId']) ? $val['pId'] : 0);
                        $queArr['pId'] = $val['id'];
                        $newRes[$id] = $queArr;
                        $queIds[$val['id']] = $id;
                        $newJsonArr['transfer_type'] = 'fixed'; //默认固定技能组；
                        $newJsonArr['variable_name'] = $nodes[$node]['variable_name'] = '';
                        $newJsonArr['queue'] = $nodes[$node]['queue'] = $val['quenum']; //技能组id;
                        $newJsonArr['if_enable_queue_timeout_continue'] = $nodes[$node]['if_enable_queue_timeout_continue'] = '0'; //是否开启排队超时继续等待功能；
                        $newJsonArr['max_queue_times'] = $nodes[$node]['max_queue_times'] = '1';
                        $newJsonArr['if_handle_none_agent'] = $nodes[$node]['if_handle_none_agent'] = '0';
                        $newJsonArr['if_handle_queue_times_exceed'] = $nodes[$node]['if_handle_queue_times_exceed'] = '0';
                        $newJsonArr['if_handle_queue_full'] = $nodes[$node]['if_handle_queue_full'] = '0';
                        $newJsonArr['if_handle_queue_timeout'] = $nodes[$node]['if_handle_queue_timeout'] = '0';
                        $newJsonArr['before_conn_sound'] = $nodes[$node]['before_conn_sound'] = array();
                        $newJsonArr['agent_side_sound'] = $nodes[$node]['agent_side_sound'] = array();
                        $newJsonArr['sound'] = $nodes[$node]['sound'] = array();
                        $nodes[$node]['children'] = array('queue_fail' => 'node'.$id);
                        $nodes['node'.$id] = array('name' => $queArr['name'], 'id' => 'node'.$id, 'parentId' => $node, 'type' => 50, 'sound' => array());
                        break;
                    case 3: //按键导航
                        $newJsonArr['play_times'] = $nodes[$node]['play_times'] = isset($val['trytimes']) && ($val['trytimes'] < 10) ? $val['trytimes'] : 10;
                        if (isset($val['timeout']) && $val['timeout'] >= 10 && $val['timeout'] <= 100) {
                            $newJsonArr['timeout'] = $nodes[$node]['timeout'] = intval($val['timeout'] / 10) * 10;
                        } elseif (isset($val['timeout']) && $val['timeout'] > 100) {
                            $newJsonArr['timeout'] = $nodes[$node]['timeout'] = 100;
                        } else {
                            $newJsonArr['timeout'] = $nodes[$node]['timeout'] = 10;
                        }
                        $newJsonArr['if_enable_multi_key'] = $nodes[$node]['if_enable_multi_key'] = 0;
                        $newJsonArr['multi_keys_start'] = $nodes[$node]['multi_keys_start'] = null;
                        $newJsonArr['multi_keys_length'] = $nodes[$node]['multi_keys_length'] = 4;
                        $newJsonArr['navigation_sound'] = $nodes[$node]['navigation_sound'] = $this->proSound($val['playfile']);
                        $newJsonArr['error_key_sound'] = $nodes[$node]['error_key_sound'] = array();
                        $newJsonArr['none_key_sound'] = $nodes[$node]['none_key_sound'] = array();
                        $navArr[] = $val['id'];//存放导航的，选择的按键；
                        break;
                    case 6: //留言
                        $newJsonArr['msgnum'] = isset($val['msgnum']) ? $val['msgnum'] : '';
                        $newJsonArr['sound'] = $nodes[$node]['sound'] = $this->proSound($val['playfile']);
                        break;
                }
                $newJsonArr['pId'] = $val['pId'];
                $newJsonArr['id'] = $val['id'];
                if (isset($navArr) && in_array($val['pId'], $navArr) && $val['name'] != '失败F') {
                    $keyword = $newJsonArr['name'] = str_replace('按键', '', $val['name']);
                    $newRes[$val['pId']]['navigation_keys'][]
                        = $nodes['node'.$val['pId']]['navigation_keys'][]
                        = $keyword;
                    $nodes['node'.$val['pId']]['children'][(string) $keyword] = 'node'.$val['id'];
                } elseif (isset($navArr) && in_array($val['pId'], $navArr) && $val['name'] == '失败F') {
                    $newJsonArr['name'] = 'F';
                    $nodes['node'.$val['pId']]['children']['F'] = 'node'.$val['id']; //失败f;
                }
                $newRes[$val['id']] = $newJsonArr;
            }
            //处理ivr_info
            //把父id转换成新的转接失败的id;
            if (!empty($queIds)) {
                $keys = array_keys($queIds);
                foreach ($newRes as $key => $val) {
                    if (in_array($val['pId'], $keys) && $key != $queIds[$val['pId']]) {
                        $newRes[$key]['pId'] = $queIds[$val['pId']];
                        $nodes['node'.$queIds[$val['pId']]]['jump'] = 'node'.$newRes[$key]['id'];
                    }
                }
            }
            $deleKey = array_diff($pids, $allPid);
            foreach ($deleKey as $val) {
                $pid = $newRes[$val]['pId'];
                $keyword = str_replace('按键', '', $newRes[$val]['name']);
                unset($newRes[$val]);
                unset($nodes['node'.$val]);
                unset($nodes['node'.$pid]['children'][(string) $keyword]); //删除nodes中的子节点；
                $key1 = array_search($keyword, $newRes[$pid]['navigation_keys']);
                $key2 = array_search($keyword, $nodes['node'.$pid]['navigation_keys']);
                unset($newRes[$pid]['navigation_keys'][(int) $key1]);
                unset($nodes['node'.$pid]['navigation_keys'][(int) $key2]);
                $newRes[$pid]['navigation_keys'] = array_values($newRes[$pid]['navigation_keys']); //变成索引数组
                $nodes['node'.$pid]['navigation_keys'] =  array_values($nodes['node'.$pid]['navigation_keys']);//变成索引数组
            }
            global $new;
            $childArr = $this->processNode($newRes);
            $ress = $this->processRes($childArr[0]);
            unset($GLOBALS['new']); //销毁全局变量；
            $str = json_encode($ress);
            $ivrInfo = json_encode($nodes);
            $conn->beginTransaction();
            try {
                $conn->update('win_ivr', array('ivr_content' => $str, 'ivr_info' => $ivrInfo, 'ivr_ver' => 1), array('ivr_id' => $row['ivr_id']));
                $result = $this->addToChangelogAndSendNoticeToZmqServer(
                    $row['ivr_id'],
                    $row['vcc_id'],
                    'create'
                );
                if ($result === false) {
                    $conn->rollBack();
                    $output->writeln($row['ivr_id']."-----update fail");
                }
                //加上记录日志
                $logFile1 = "/var/log/manage/ivr_content_transformation_".date('Y-m-d').".txt";
                $logFile2 = "/var/log/manage/ivr_info_transformation_".date('Y-m-d').".txt";
                file_put_contents($logFile1, $row['ivr_id'].'-----------'.$row['ivr_content'].'===>'.$str."\r\n", FILE_APPEND);
                file_put_contents($logFile2, $row['ivr_id'].'-----------'.$row['ivr_info'].'===>'.$str."\r\n", FILE_APPEND);
                $conn->commit();
                $output->writeln($row['ivr_id']."-----update success");
            } catch (\Exception $e) {
                $conn->rollBack();
                $output->writeln($row['ivr_id']."-----update fail [".$e->getMessage().']');
            }
        }
        $output->writeln("end");
    }

    /**
     * @param $items
     * @return array
     */
    private function processNode($items)
    {
        $tree = array();
        foreach ($items as $item) {
            if (isset($items[$item['pId']])) {
                $items[$item['pId']]['jump'] = &$items[$item['id']]['type'];
                $items[$item['pId']]['children'][] = &$items[$item['id']];
            } else {
                $tree[] = &$items[$item['id']];
            }
        }

        return $tree;
    }

    /**
     * 处理语音
     * @param $sounds
     * @return array
     */
    private function proSound($sounds)
    {
        if (!empty($sounds)) {
            $dirAddress = $this->getContainer()->getParameter('sound_local_upload_path'); //语音文件路径
            $sound = array(
                array(
                    'sound_type' => '1',
                    //'sound_list'=>str_replace('ccod', $dir_address, $sounds.'.wav'),
                    'sound_list' => str_replace('ccod', $dirAddress, $sounds.'.wav'),
                    'sound_number' => '',
                ),
            );

            return $sound;
        }

        return array();
    }

    /**
     * 处理最终结果
     *
     * @param string $arr
     *
     * @return array
     */
    public function processRes($arr)
    {
        global $new;
        $new[] = $arr;
        if (isset($arr['children'])) {
            if (isset($arr['children'][0]) && is_array($arr['children'][0])) {
                foreach ($arr['children'] as $child) {
                    $this->processRes($child);
                }
            } else {
                $this->processRes($arr['children']);
            }
        }

        return $new;
    }


    /**
     * 添加更新记录表，以及通知分发服务有更新
     *
     * @param int $ivrId 更新的语音ID
     * @param int $vccId 企业id
     * @param string $logAction 操作(create,update)
     * @return bool
     */
    private function addToChangelogAndSendNoticeToZmqServer($ivrId, $vccId, $logAction = 'update')
    {
        if (empty($ivrId)) {
            return false;
        }

        $conn = $this->getContainer()->get('doctrine.dbal.default_connection');

        $logger = $this->getContainer()->get('logger');
        //添加更新记录表
        $changelog = array(
            'vcc_id' => $vccId,
            'log_type' => 'ivr',
            'log_action' => $logAction,
            'table_id' => $ivrId,
        );
        $ret = $conn->insert('cc_cti_change_logs', $changelog);
        $nid = $conn->lastInsertId();
        if ($ret <= 0) {
            $logger->critical(sprintf('Insert value %s to table cc_cti_change_logs failed.', json_encode($changelog)));

            return false;
        }

        //发送通知
        $zmqServer = $this->getContainer()->getParameter('cti_zmq_server');
        $zmqPort = $this->getContainer()->getParameter('cti_zmq_port');

        try {
            $context = new \ZMQContext();
            $requester = new \ZMQSocket($context, \ZMQ::SOCKET_REQ);
            $requester->connect("tcp://$zmqServer:$zmqPort");
            $msg = json_encode(array('nid' => intval($nid)));
            $requester->send($msg);
            $logger->info(sprintf('Send the request to the server %s:%s, the msg is %s.', $zmqServer, $zmqPort, $msg));

            $poll = new \ZMQPoll();
            $poll->add($requester, \ZMQ::POLL_IN);
            $readable = $writeable = array();
            $events = $poll->poll($readable, $writeable, 5000);
            $errors = $poll->getLastErrors();

            //存在错误
            if (count($errors) > 0) {
                foreach ($errors as $error) {
                    $logger->critical(sprintf("Error polling object, the error is %s", $error));

                    return false;
                }
            }

            //收到消息
            if ($events > 0) {
                foreach ($readable as $socket) {
                    if ($socket === $requester) {
                        $reply = $requester->recv();
                    }
                }
            } else {
                return false;
            }

            if (empty($reply)) {
                $logger->critical(sprintf('The reply of the request is empty, needs json.'));

                return false;
            }
            $replyArray = json_decode($reply, true);
            $jsonLastError = json_last_error();
            if ($jsonLastError != JSON_ERROR_NONE) {
                $logger->critical(sprintf('Json decode the reply %s failed, the error is %s.', $reply, $jsonLastError));

                return false;
            }

            $ret = isset($replyArray['ret']) ? $replyArray['ret'] : '-1';
            if ($ret === 0) {
                return true;
            } else {
                $logger->critical(sprintf('The ret of the reply %s is not 0, the reply is %s.', $ret, $reply));

                return false;
            }
        } catch (\ZMQPollException $e) {
            $logger->critical(sprintf('Poll failed: %s', $e->getMessage()));

            return false;
        }
    }
}
